﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

// PostSharp AOP Library
using PostSharp.Aspects;


namespace Theoreme.Teaching.AOP.Sample01
{

    /// <summary>
    /// Notre Aspect est implémenté sous la forme d'un attribut.
    /// <see cref="OnMethodfBoundaryAspect"/> dérive en effet de Attribute.
    /// De plus la classe d'Aspect DOIT être Serializable.
    /// </summary>
    [Serializable]
    public sealed class TraceAttribute : OnMethodBoundaryAspect
    {
        private readonly string _category;

        /// <summary>
        /// Initializes a new instance of the <see cref="TraceAttribute"/> class.
        /// </summary>
        /// <param name="category">The category.</param>
        public TraceAttribute(string category)
        {
            this._category = category;
        }


        /// <summary>
        /// Method executed <b>before</b> the body of methods to which this aspect is applied.
        /// </summary>
        /// <param name="args">Event arguments specifying which method
        /// is being executed, which are its arguments, and how should the execution continue
        /// after the execution of <see cref="M:PostSharp.Aspects.IOnMethodBoundaryAspect.OnEntry(PostSharp.Aspects.MethodExecutionArgs)"/>.</param>
        public override void OnEntry(MethodExecutionArgs args)
        {
            Trace.WriteLine(string.Format("- Entering method {0}.{1}.",
                                          args.Method.DeclaringType.FullName, 
                                          args.Method.Name), 
                            this._category);

            Trace.Indent();

        }


        /// <summary>
        /// Method executed <b>after</b> the body of methods to which this aspect is applied,
        /// even when the method exists with an exception (this method is invoked from
        /// the <c>finally</c> block).
        /// </summary>
        /// <param name="args">Event arguments specifying which method
        /// is being executed and which are its arguments.</param>
        public override void OnExit(MethodExecutionArgs args)
        {
            Trace.Unindent();

            Trace.WriteLine(string.Format("- Exiting method{0}.{1}.\r\n",
                                          args.Method.DeclaringType.Name, 
                                          args.Method.Name), 
                            this._category);                        
        }

        /// <summary>
        /// Method executed <b>after</b> the body of methods to which this aspect is applied,
        /// in case that the method resulted with an exception.
        /// </summary>
        /// <param name="args">Event arguments specifying which method
        /// is being executed and which are its arguments.</param>
        public override void OnException(MethodExecutionArgs args)
        {
            Trace.Unindent();
            
            Trace.WriteLine(string.Format("- Leaving {0}.{1} with exception {2}.",
                                          args.Method.DeclaringType.FullName,
                                          args.Method.Name,
                                          args.Exception.GetType().Name),
                             _category);
        }


        /// <summary>
        /// Gets the category.
        /// </summary>
        public string Category { get { return _category; } }
    }
}
